/*
 * SecIndex.cpp
 *
 *  Created on: 02/11/2009
 *      Author: ngonzalez
 */


#include "../Externa/Clave.h"
#include "../Strategies/Index/SecIndex.h"

enum indexType {BSharp , Hash, SecuencialIndex };

SecIndex::SecIndex() {

}

SecIndex::~SecIndex() {
	delete this->almacenamiento;
}


void SecIndex::SetStorageStrategy(StorageStrategy *storage){
	this->storageStrategy = storageStrategy;
}

StorageStrategy * SecIndex::GetStorageStrategy() const{
	return this->storageStrategy;
}

void SecIndex::saludar(){}

/**
 * Verifica la unicidad de la clave a insertar en el indice
 */
bool SecIndex::checkUniqueness(Clave *clave, Dato *dato) {

	Almacenamiento * storage = this->getStorage();

    string linea;
    string claveArchivo;

    storage->firstPosition();

    while (!storage->isEoS()) {

    	linea = storage->getData();

    	int posicion = linea.find("|");

    	claveArchivo = linea.substr(0,posicion);

    	cout << claveArchivo << "vs" << clave->getClave() << endl;

    	if (claveArchivo.compare(clave->getClave().c_str()) == 0 ){
    		return false;
    	}
    }
	return true;
}

/**
 * Luego de una insercion/modificacion en disco, actualiza el indice con la referencia al
 * archivo (Numero de bloque,registro o linea en caso de los archivo de texto)
 */
void SecIndex::updateIndex(int fileReference,Clave *clave, Dato *dato) {

	std::string s;
	std::stringstream out;
	out << fileReference;
	s = out.str();

	string indexData = clave->getClave() +"|"+ s;
	this->getStorage()->saveData(indexData);
}

/**
 * Metodo que, apartir de una clave, me devuelve la posicion en la que se
 * encuentra el dato correspondiente a esa clave, en la estructura que se esta
 * usando (Archivo o Buffer)
 * En caso de no encontrarla, devuelve un valor negativo.
 */
int SecIndex::getStorageReferenceByKey(Clave *clave){

	Almacenamiento * storage = this->getStorage();

	string linea;
	string claveArchivo;
	int fileReference = 0;

	storage->firstPosition();

	while (!storage->isEoS()) {

		linea = storage->getData();

		int posicion = linea.find("|");

		claveArchivo = linea.substr(0,posicion);

		cout << claveArchivo << "vs" << clave->getClave() << endl;

		if (claveArchivo.compare(clave->getClave().c_str()) == 0 ){
			return fileReference;
		}
		fileReference++;
	}
	return -1;
}

/**
 * Metodo que que borra la clave del indice actualizandolo.Devuelve un numero negativo en caso de error.
 */
int SecIndex::deleteKey(Clave *clave){

	Almacenamiento * storage = this->getStorage();

	string linea;
	string claveArchivo;

	storage->firstPosition();

	while (!storage->isEoS()) {

		int lastPosition = storage->getPosition();

		linea = storage->getData();

		int posicion = linea.find("|");

		claveArchivo = linea.substr(0,posicion);

		cout << claveArchivo << "vs" << clave->getClave() << endl;

		if (claveArchivo.compare(clave->getClave().c_str()) == 0 ){
			storage->deleteCurrent(lastPosition);
			return 1;
		}

	}
	return -1;
}

/**
 * Workaround agregado, dado que las distintas estrategias de indexado comparten una misma interfaz, y su comportamiento no se el mismo
 * Problema de Arquitectura.
 */
int SecIndex::getClassName(){
	return SecuencialIndex;
}

Almacenamiento * SecIndex::getStorage() const{
	return this->almacenamiento;
}

void SecIndex::setStorage(Almacenamiento *storage){
	this->almacenamiento = storage;
}
